package com.application.race.manage;

import java.io.ByteArrayInputStream;
import java.io.File;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.core.utils.Base64;
import com.core.utils.ZLibUtil;

public class MapFactory {
	static XPath xpath;
	static Document document;
	private static final String ITEMDATA_FILE_PATH = "res/map/";

	// public static String xmlPath = new
	// SysInfo().getCurPath()+SysInfo.fileSeparator;
	public static MapInfo loadMap(String url) {
		try {
			MapInfo map = new MapInfo();
			String s = MapFactory.class.getResource("").getPath();
			DocumentBuilder builder = DocumentBuilderFactory.newInstance()
					.newDocumentBuilder();
			// System.out.println( new SysInfo().getCurPath());
			document = builder.parse(new File(ITEMDATA_FILE_PATH + url));
			xpath = XPathFactory.newInstance().newXPath();
			readMapInfo(map);
			return map;

		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	private static void readMapInfo(MapInfo map) throws Exception {
		String expression = "/map";
		Node mapRoot = (Node) xpath.evaluate(expression, document,
				XPathConstants.NODE);
		NamedNodeMap nodeMap = mapRoot.getAttributes();
		map.width_in_tiles = Integer.parseInt(nodeMap.getNamedItem("width")
				.getNodeValue());
		int tile_width = Integer.parseInt(nodeMap.getNamedItem("tilewidth")
				.getNodeValue());
	    map.firctCft=Double.parseDouble(nodeMap.getNamedItem("firctCft").getNodeValue());
		// log.info("map_width "+map_width);
		map.map_width = map.width_in_tiles * tile_width;

		map.height_in_tiles = Integer.parseInt(nodeMap.getNamedItem("height")
				.getNodeValue());
		int tile_height = Integer.parseInt(nodeMap.getNamedItem("tileheight")
				.getNodeValue());
		// log.info("map_width "+map_width);
		map.map_height = map.height_in_tiles * tile_height;
		map.physIdx = new int[map.width_in_tiles * map.height_in_tiles];
		// map.viewIdx=new int[ map.width_in_tiles* map.height_in_tiles];

		readInfos(map, mapRoot);

	}

	static void readSites(MapInfo map, Node rootNode) {

	}

	static void readLayer(MapInfo map, Node layer) throws Exception {
		NamedNodeMap nodeMap = layer.getAttributes();
		String name = nodeMap.getNamedItem("name").getNodeValue();

		if (name.equals("phylayer")) {
			Node data = getSubNode(layer, "data");
			char[] charArray = data.getTextContent().trim().toCharArray();
			byte[] dec = Base64.decode(charArray);
			dec = ZLibUtil.decompress(dec);
			ByteArrayInputStream is = new ByteArrayInputStream(dec);
			// InputStream is = new GZIPInputStream(bais);

			int point = 0;

			for (int y = 0; y < map.height_in_tiles; y++) {
				for (int x = 0; x < map.width_in_tiles; x++) {
					int tileId = 0;
					tileId |= is.read();
					tileId |= is.read() << 8;
					tileId |= is.read() << 16;
					tileId |= is.read() << 24;

					map.physIdx[point] = tileId;
					point++;

				}
			}

		}
	}

	static void readInfos(MapInfo map, Node rootNode) throws Exception {
		NodeList list = rootNode.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			Node node = list.item(i);

			if (node.getNodeName().equals("layer")) {
				readLayer(map, node);
			}
			if (node.getNodeName().equals("entrance")) {
				readEntrance(map, node);
			}
		}

	}

	private static void readEntrance(MapInfo map, Node entrance)
			throws Exception {
		NamedNodeMap nodeMap = entrance.getAttributes();
		int size = Integer
				.parseInt(nodeMap.getNamedItem("size").getNodeValue());
		map.sitex = new int[size];
		map.sitey = new int[size];
		// log.info("entrance  size "+size);
		NodeList list = entrance.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			Node site = list.item(i);
			if (!site.getNodeName().equals("site"))
				continue;
			nodeMap = site.getAttributes();
			int id = Integer
					.parseInt(nodeMap.getNamedItem("id").getNodeValue());
			int x = Integer.parseInt(nodeMap.getNamedItem("x").getNodeValue());
			int y = Integer.parseInt(nodeMap.getNamedItem("y").getNodeValue());
			map.sitex[id] = x;
			map.sitey[id] = y;
		}
	}

	static Node getSubNode(Node rootNode, String nodeName) throws Exception {
		NodeList list = rootNode.getChildNodes();
		for (int i = 0; i < list.getLength(); i++) {
			Node node = list.item(i);

			if (node.getNodeName().equals(nodeName)) {
				return node;
			}
		}
		return null;
	}
}
